

#include <stm32f0xx.h>
#define _CM0_
#include <setjmp.h>
unsigned int Coro_GetTickMs()
{
    return HAL_GetTick();
}
static void prvTaskExitError( void )
{
	while(1){;}
}
static unsigned int* firstTaskStack;

#ifdef _CM0_
void Coro_start( jmp_buf buf )
{
	firstTaskStack=buf;
	__asm volatile("	ldr r0, pxCurrentTCBConst2					\n" /* The first item in pxCurrentTCB is the task top of stack. */
					"	ldr r0, [r0]			\n"
					"	add    r0, #16			\n"
					"	ldmia r0!, {r2-r6}		\n"
					"	mov r8, r2				\n"
					"	mov r9, r3				\n"
					"	mov r10, r4				\n"
					"	mov r11, r5				\n"
					"	msr psp, r6				\n"
					"	ldmia   r0!, {r3} 		\n"
					"  	sub    r0, #40			\n"
					"  	ldmia   r0!, {r4, r5, r6, r7}\n"
					"	mov r0, #2					\n"/* Switch to the psp stack. */
			        "	msr  CONTROL, r0				\n"
					"	bx r3							\n"
					"									\n"
					"	.align 4					\n"
					"	pxCurrentTCBConst2: .word firstTaskStack	\n");
}
#else
void Coro_start( jmp_buf buf )
{
	unsigned int * pxTopOfStack=buf[8];
	pxTopOfStack--;

	*pxTopOfStack = 0x01000000;//portINITIAL_XPSR;	/* xPSR */
	pxTopOfStack--;
	*pxTopOfStack = buf[9]&0xfffffffeUL;//( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;	/* PC */
	pxTopOfStack--;
	*pxTopOfStack = prvTaskExitError;	/* LR */

	/* Save code space by skipping register initialisation. */
	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
	*pxTopOfStack = 0;	/* R0 */

	/* A save method is being used that requires each task to maintain its
	own exec return value. */
	pxTopOfStack--;
	*pxTopOfStack = 0xfffffffd ;//portINITIAL_EXC_RETURN;
	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
	firstTaskStack =pxTopOfStack;
	/* Start the first task.  This also clears the bit that indicates the FPU is
	in use in case the FPU was used before the scheduler was started - which
	would otherwise result in the unnecessary leaving of space in the SVC stack
	for lazy saving of FPU registers. */
	__asm volatile(
					" ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */
					" ldr r0, [r0] 			\n"
					" ldr r0, [r0] 			\n"
					" msr msp, r0			\n" /* Set the msp back to the start of the stack. */
					" mov r0, #0			\n" /* Clear the bit that indicates the FPU is in use, see comment above. */
					" msr control, r0		\n"
					" cpsie i				\n" /* Globally enable interrupts. */
					" cpsie f				\n"
					" dsb					\n"
					" isb					\n"
					" svc 0					\n" /* System call to start first task. */
					" nop					\n"
				);
}
void SVC_Handler(void)
{
	__asm volatile (
					"	ldr r0, pxCurrentTCBConst2					\n" /* The first item in pxCurrentTCB is the task top of stack. */
					"	ldr r0, [r0]					\n"
					"	ldmia r0!, {r4-r11, r14}		\n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
					"	msr psp, r0						\n" /* Restore the task stack pointer. */
					"	mov r0, #3 						\n"
					"	bx r14							\n"
					"	.align 4						\n"
					"	pxCurrentTCBConst2: .word firstTaskStack	\n"
				);
}
#endif

